import 'dart:io';

import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:flutter/foundation.dart';

import '../config/env_config.dart';
import '../plugins/custom_parsing.dart';
import '../plugins/network_logger.dart';
import '../plugins/network_mock.dart';
import 'network_interceptor.dart';
import 'network_request.dart';
import 'network_response.dart';

/// 网络核心
class NetworkProvider {
  /// 单例
  static final NetworkProvider shared = NetworkProvider._();

  factory NetworkProvider() => shared;

  /// 请求实例
  final _provider = Dio();

  NetworkProvider._() {
    _loadOptions();
  }

  /// 某些插件需要使用
  Dio get provider => _provider;

  /// 加载默认配置
  _loadOptions() {
    /// 添加抓包代理
    _addProxy();

    /// 添加插件
    final List<NetworkInterceptor> interceptors = [CustomParsing()];

    if (HMNetworkConfig.openMock) {
      interceptors.add(NetworkMock());
    }
    if (HMNetworkConfig.openLog) {
      interceptors.add(NetworkLogger());
    }

    /// 根据插件优先级排序
    interceptors.sort((a, b) => a.priority.compareTo(b.priority));
    _provider.interceptors.addAll(interceptors);
  }

  /// 添加代理
  _addProxy() async {
    if (kIsWeb) {
      return;
    }
    switch (HMNetworkConfig.environment) {
      case NetEnvironment.PROD:
        break;
      default:
        String proxyStr = HMNetworkConfig.proxy;
        if (proxyStr.isEmpty) return;
        final proxy = proxyStr.isNotEmpty ? 'PROXY $proxyStr' : 'DIRECT';
        _provider.httpClientAdapter = IOHttpClientAdapter(
          createHttpClient: () {
            final client = HttpClient();
            client.findProxy = (uri) {
              /// 将请求代理至 localhost:8888。
              /// 请注意，代理会在你正在运行应用的设备上生效，而不是在宿主平台生效。
              return proxy;
            };
            return client;
          },
        );
    }
  }

  /// 发起请求
  Future<ResponseResult<T>> request<T>(
    TargetType target, {
    CancelToken? cancelToken,
    ProgressCallback? onReceiveProgress,
    ProgressCallback? onSendProgress,
    Map<String, dynamic>? queryParameters,
    dynamic data,
    Map<String, dynamic>? headers,
    TransformValue<T>? transformer,
  }) async {
    RequestOptions requestOptions = RequestOptions(
      method: target.method.rawValue,
      baseUrl: target.baseUrl,
      path: target.fullPath(),
      headers: headers,
      connectTimeout: target.connectTimeout,
      receiveTimeout: target.receiveTimeout,
      sendTimeout: target.sendTimeout,
      contentType: target.contentType,
      responseType: target.responseType,
      cancelToken: cancelToken,
      onReceiveProgress: onReceiveProgress,
      onSendProgress: onSendProgress,
      queryParameters: queryParameters,
      data: data,
    );
    requestOptions.extra[MappingKey.target] = target;
    requestOptions.extra[MappingKey.transformer] = transformer;
    final result = ResponseResult<T>();
    try {
      final response = await _provider.fetch(requestOptions);
      final data = response.data;
      if (data is ResponseResult) {
        /// 已经是插件处理后的结果
        if (!data.isSuccess && target.showErrorToast) {
          print(data.exception?.message);
        }
        return ResponseResult.copyWith(data);
      } else {
        result.data = data;
        if (transformer != null) {
          result.data = transformer(data);
        }
      }
      return result;
    } catch (error) {
      /// 任何http请求异常（比如404）都会被转换为NetworkException
      if (error is DioException && error.error is NetworkException) {
        result.exception = error.error as NetworkException;
      } else {
        result.exception = NetworkException.system();
      }
      if (target.showErrorToast) {
        print(result.exception?.message);
      }
      return result;
    }
  }
}
